package com.sunseen.capacitormachine.data;

import android.util.Log;
import android.util.SparseArray;

import androidx.annotation.IntDef;

import com.sunseen.capacitormachine.commumication.serialport.event.OvenChainUpdateEvent;
import com.sunseen.capacitormachine.commumication.serialport.event.SurgeParameterEvent;
import com.sunseen.capacitormachine.commumication.tcp.event.SendOvenParamEvent;
import com.sunseen.capacitormachine.data.bean.CapacitorBean;
import com.sunseen.capacitormachine.data.bean.DetectionFlagBean;
import com.sunseen.capacitormachine.data.bean.HolderBean;
import com.sunseen.capacitormachine.data.bean.HolderBean_;
import com.sunseen.capacitormachine.data.bean.IndexBean;
import com.sunseen.capacitormachine.data.bean.PosBean;
import com.sunseen.capacitormachine.data.bean.ProducingParameter;
import com.sunseen.capacitormachine.modules.query.bean.FlowCard;
import com.sunseen.capacitormachine.modules.realtime.event.SetSurgeLineEvent;

import org.greenrobot.eventbus.EventBus;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;

import io.objectbox.Box;
import io.objectbox.query.QueryBuilder;

/**
 * 记录并处理电容数据的工具类
 */
public final class DataUtil {

    public static String DeviceNo = "6812B066";

    public static final String DefaultBatchId = "-111";//默认的单号，用于软件判断使用

    public static String FlowCardBatchId = DefaultBatchId;//切换下发参数的单号

    public static String FlowCardBatchIdProducing = DefaultBatchId;//生产中的单号
    /**
     * 当前生产中使用到的一些参数
     */
    public static ProducingParameter producingParameter;

    /**
     * 将生产中的数据下发到红外模块，浪涌模块
     */
    public static void sendProducingParameter() {
        /**
         * 将浪涌上限发送给浪涌模块
         * */
        EventBus.getDefault().post(new SurgeParameterEvent(producingParameter.getSurgeUpperLimitVoltage()));
        /**
         * 将红外参数发送给红外模块
         * */
        EventBus.getDefault().post(new SendOvenParamEvent(
                producingParameter.getImplosionTime(),
                producingParameter.getImplosionUpperLimitCurrent(),
                producingParameter.getImplosionLowerLimitCurrent(),
                producingParameter.getImplosionUpperLimitVoltage(),
                producingParameter.getImplosionLowerLimitVoltage()));

        /**
         * 发出此事件，更新实时数据界面的浪涌曲线图的基准线
         * */
        EventBus.getDefault().post(new SetSurgeLineEvent(producingParameter.getSurgeUpperLimitVoltage()));
    }

    public static void saveProducingParameter() {
        producingParameterBox.put(producingParameter);
    }

    /**
     * 在烤箱内的最后一个非空电容的uid
     */
    public static String ovenLastCapacitorUid = null;

    /**
     * 记录每一批电容最后一个进烤箱的电容的ID
     */
    public static final ConcurrentLinkedQueue<String> lastCapacitorUidQueue = new ConcurrentLinkedQueue<>();

    /**
     * 记录烤箱内夹具的双端列表
     */
    public static final LinkedList<HolderBean> holderList = new LinkedList<>();
    public static final SparseArray<HolderBean> holderSparseArray = new SparseArray<>();

    public static final LinkedList<HolderBean> chainHolderList = new LinkedList<>();

    private static Box<ProducingParameter> producingParameterBox;
    private static Box<IndexBean> offsetBeanBox;
    private static Box<HolderBean> holderBeanBox;
    public static IndexBean offsetBean;


    public static void initData() {
        producingParameterBox = ObjectBox.getBoxStore().boxFor(ProducingParameter.class);
        QueryBuilder<ProducingParameter> producingParameterQueryBuilder = producingParameterBox.query();
        producingParameter = producingParameterQueryBuilder.build().findFirst();
        if (producingParameter == null) {
            producingParameter = new ProducingParameter("888888", 1000, 10, 600, 10, 1, 480);
        }
        offsetBeanBox = ObjectBox.getBoxStore().boxFor(IndexBean.class);
        holderBeanBox = ObjectBox.getBoxStore().boxFor(HolderBean.class);
        flagBeanBox = ObjectBox.getBoxStore().boxFor(DetectionFlagBean.class);
        QueryBuilder<IndexBean> queryBuilder = offsetBeanBox.query();
        offsetBean = queryBuilder.build().findFirst();
        if (offsetBean == null) {
            offsetBean = new IndexBean();
            offsetBean.setOffset(0);
            offsetBeanBox.put(offsetBean);
        }
        Log.e("test", "offset = " + offsetBean.getOffset());
        QueryBuilder<DetectionFlagBean> flagQueryBuilder = flagBeanBox.query();
        flagBean = flagQueryBuilder.build().findFirst();
        if (flagBean == null) {
            flagBean = new DetectionFlagBean();
            flagBeanBox.put(flagBean);
        }
        recoverData();

    }

    public static DetectionFlagBean flagBean;
    private static Box<DetectionFlagBean> flagBeanBox;

    public static void saveDetectionFlagBean() {
        flagBeanBox.put(flagBean);
    }

    public static void saveOffset(int offset) {
        offsetBean.setOffset(offset);
        offsetBeanBox.put(offsetBean);
    }

    /**
     * 待生产
     */
    public final static int ToBeProduce = 0;
    /**
     * 生产暂停
     */
    public final static int ProducePause = 1;
    /**
     * 生产中
     */
    public final static int Producing = 2;

    @IntDef({ToBeProduce, ProducePause, Producing})
    @Retention(RetentionPolicy.SOURCE)
    public @interface ProduceState {
    }

    /**
     * 当前机器的生产状态
     */
    private static @ProduceState
    int produceState = ToBeProduce;

    public static void setProduceState(@ProduceState int state) {
        produceState = state;
    }

    public static @ProduceState
    int getProduceState() {
        return produceState;
    }

    public static final int DEFAULT_ID = -1000;
    public static volatile int TapHolderId = DEFAULT_ID;
    public static volatile int CurrentHolderId = DEFAULT_ID;
    public static volatile int CurrentCapacitorPos = DEFAULT_ID;

    public static void setCurrentCapacitorPos(int pos) {
        CurrentCapacitorPos = pos;
        CurrentHolderId = TapHolderId;
    }

    public static void reCoverCurrentCapacitorPos() {
        CurrentCapacitorPos = DEFAULT_ID;
        CurrentHolderId = DEFAULT_ID;
    }


    private static void reBuildData() {
        holderList.clear();
        chainHolderList.clear();
        Box<CapacitorBean> capacitorBeanBox = ObjectBox.getBoxStore().boxFor(CapacitorBean.class);
        List<HolderBean> list = holderBeanBox.getAll();
        if (list.size() > 0) {
            for (HolderBean holderBean : list) {
                capacitorBeanBox.remove(holderBean.capacitorList);
            }
            holderBeanBox.remove(list);
        }
        List<HolderBean> chainHolderBeanList = new ArrayList<>();
        for (int i = 0; i < Constant.ChainHolderInitSize; i++) {
            HolderBean holderBean = new HolderBean(i + 1, false);
            for (int j = 0; j < 21; j++) {
                int sequence = i * 21 + j;
                CapacitorBean capacitorBean = new CapacitorBean(String.valueOf(sequence), sequence, true);
                holderBean.capacitorList.add(capacitorBean);
            }
            chainHolderBeanList.add(holderBean);
        }
        holderBeanBox.put(chainHolderBeanList);
        chainHolderList.addAll(chainHolderBeanList);

        List<HolderBean> holderBeanList = new ArrayList<>();
        for (int i = Constant.ChainHolderInitSize, size = Constant.HolderInitSize + Constant.ChainHolderInitSize; i < size; i++) {
            HolderBean holderBean = new HolderBean(i + 1, true);
            DataUtil.holderSparseArray.put(i, holderBean);
            for (int j = 0; j < 21; j++) {
                int sequence = i * 21 + j;
                CapacitorBean capacitorBean = new CapacitorBean(String.valueOf(sequence), sequence, true);
                holderBean.capacitorList.add(capacitorBean);
            }
            holderBeanList.add(holderBean);
        }
        holderBeanBox.put(holderBeanList);
        holderList.addAll(holderBeanList);
    }

    private static void recoverData() {
        QueryBuilder<HolderBean> chainHolderQueryBuilder = holderBeanBox.query();
        List<HolderBean> chainHolderBeanList = chainHolderQueryBuilder.equal(HolderBean_.inOven, false).build().find();
        int chainHolderSize = chainHolderBeanList.size();
        QueryBuilder<HolderBean> holderQueryBuilder = holderBeanBox.query();
        List<HolderBean> holderBeanList = holderQueryBuilder.equal(HolderBean_.inOven, true).build().find();
        int holderBeanListSize = holderBeanList.size();
        if (holderBeanListSize == 0 || chainHolderSize == 0) {
            reBuildData();
        } else {
            chainHolderList.addAll(chainHolderBeanList);
            holderList.addAll(holderBeanList);
        }
        for (HolderBean holderBean : holderList) {
            holderSparseArray.put(holderBean.getHolderId(), holderBean);
        }
        Log.e("test", "chainHolderSize = " + chainHolderBeanList.size());
        Log.e("test", "holderSize = " + holderBeanList.size());
    }

    public static void recoverDataToInit() {
        if (offsetBeanBox == null) {
            offsetBeanBox = ObjectBox.getBoxStore().boxFor(IndexBean.class);
        }
        QueryBuilder<IndexBean> queryBuilder = offsetBeanBox.query();
        offsetBean = queryBuilder.build().findFirst();
        if (offsetBean == null) {
            offsetBean = new IndexBean();
            offsetBean.setOffset(0);
            offsetBeanBox.put(offsetBean);
        } else {
            offsetBean.setOffset(0);
            offsetBeanBox.put(offsetBean);
        }
        reBuildData();
    }

    /**
     * 进出料链条头尾循环移动,由于烤箱第三层出料处有
     */
    public static void chainHolderCircleMove() {
        HolderBean chainHolderBean2 = chainHolderList.pollLast();
        HolderBean chainHolderBean = chainHolderList.pollFirst();
        if (chainHolderBean != null && chainHolderBean2 != null) {
            HolderBean holderBean = new HolderBean(chainHolderBean.getHolderId(), false);
            holderBean.capacitorList.addAll(chainHolderBean.capacitorList);
            holderBeanBox.remove(chainHolderBean);
            holderBeanBox.put(holderBean);
            chainHolderList.add(holderBean);

            HolderBean holderBean2 = new HolderBean(chainHolderBean2.getHolderId(), false);
            holderBean2.capacitorList.addAll(chainHolderBean2.capacitorList);
            holderBeanBox.remove(chainHolderBean2);
            holderBeanBox.put(holderBean2);
            chainHolderList.add(holderBean2);
        }
    }

    public static void holderMoveIntoOven() {
        HolderBean chainHolderBean = chainHolderList.pollFirst();
        if (chainHolderBean != null) {
            HolderBean holderBean = new HolderBean(chainHolderBean.getHolderId(), true);
            holderBean.capacitorList.addAll(chainHolderBean.capacitorList);
            holderBeanBox.remove(chainHolderBean);
            holderBeanBox.put(holderBean);
            holderList.add(holderBean);
            DataUtil.holderSparseArray.put(holderBean.getHolderId(), holderBean);
            EventBus.getDefault().post(new OvenChainUpdateEvent());
        }
    }

    public static void holderMoveIntoChain() {
        if (holderList.size() > 326) {
            HolderBean holderBean = holderList.pollFirst();
            if (holderBean != null) {
                HolderBean chainHolderBean = new HolderBean(holderBean.getHolderId(), false);
                chainHolderBean.capacitorList.addAll(holderBean.capacitorList);
                holderBeanBox.remove(holderBean);
                holderBeanBox.put(chainHolderBean);
                chainHolderList.add(chainHolderBean);
                DataUtil.holderSparseArray.delete(holderBean.getHolderId());
                EventBus.getDefault().post(new OvenChainUpdateEvent());
            }
        }
    }

    public static PosBean getChainPosBean(int pos) {
        int holderPos = pos / 21;
        int capacitorPos = pos % 21;
        boolean inIndex = holderPos < chainHolderList.size();
        return new PosBean(inIndex, holderPos, capacitorPos);
    }

    public static CapacitorBean getChainCapacitorBean(int holderPos, int capacitorPos) {
        return chainHolderList.get(holderPos).getCapacitorList().get(capacitorPos);
    }

}

